home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 7
/
Amiga Format AFCD07 (Dec 1996, Issue 91).iso
/
serious
/
shareware
/
comms
/
internet
/
html-related
/
hsc
/
source
/
hsclib
/
skip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-03
|
17KB
|
629 lines
/*
* skip.c
*
* functions for skipping several things
*
* Copyright (C) 1995,96 Thomas Aglassinger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* updated: 30-Jul-1996
* created: 8-Oct-1995
*/
#define NOEXTERN_HSCLIB_SKIP_H
#include "hsclib/inc_base.h"
#include "hsclib/input.h"
#include "hsclib/skip.h"
/* debug skip */
#if 1
#define DS(x) if(hp->debug) x
#else
#define DS(x)
#endif
#define DHLS "*hsclib* skip: "
/*
* skip_lf
*
* ignore '\n'
*
* params: inpf...input file to read char from
* result: TRUE if skipped
*/
BOOL skip_lf(HSCPRC * hp)
{
/*
* TODO: check, why skip_lf() should not be allowed to
* change the infp's current word
*/
/* TODO: skip white-spaces after linefeed, if COMPACT set */
INFILE *inpf = hp->inpf;
#if 0
int nc = infgetc(inpf);
if (nc != '\n')
inungetc(nc, inpf);
return ((BOOL) (nc == EOF));
#else
BOOL skipped = FALSE;
STRPTR nw = infgetw(inpf);
if (nw)
if (strcmp(nw, "\n"))
inungetcwws(inpf);
else
{
if (hp->compact && !(hp->inside_pre))
{
if (infskip_ws(inpf))
{
DMSG("skipped whtspc after LF");
}
}
skipped = TRUE;
}
return skipped;
#endif
}
/*
* skip_lfs
*
* skip until any <> LF is found
*
* params: inpf...input file to read(s) char from
* result: TRUE if skipped at least one LF
*/
BOOL skip_lfs(HSCPRC * hp)
{
BOOL skipped_any = FALSE;
INFILE *inpf = hp->inpf;
STRPTR nw = infgetw(inpf);
/* skip linefeeds */
while (nw && (!strcmp(nw, "\n")))
{
skipped_any = TRUE;
nw = infgetw(inpf);
}
/* write back last white spaces and word */
if (nw)
inungetcwws(inpf);
return (skipped_any);
}
BOOL eot_reached(HSCPRC * hp, BYTE * state)
{
INFILE *inpf = hp->inpf;
STRPTR nw = infgetw(inpf);
if (nw)
{
switch (*state)
{
case TGST_TAG:
if (!strcmp(nw, "\""))
*state = TGST_DQUOTE;
else if (!strcmp(nw, "'"))
*state = TGST_QUOTE;
/* TODO: skip references & expressions */
#if 0
else if (!strcmp(nw, "<"))
*state = TGST_REF;
#endif
else if (!strcmp(nw, ">"))
*state = TGST_END;
break;
case TGST_REF:
case TGST_QUOTE:
case TGST_DQUOTE:
if (strcmp(nw, "\n"))
{
switch (*state)
{
case TGST_REF:
if (!strcmp(nw, ">"))
*state = TGST_TAG;
break;
case TGST_QUOTE:
if (!strcmp(nw, "'"))
*state = TGST_TAG;
break;
case TGST_DQUOTE:
if (!strcmp(nw, "\""))
*state = TGST_TAG;
break;
}
}
else
{
/* unexpected end of line */
hsc_msg_eol(hp);
*state = TGST_TAG; /* go on reading inside tag */
}
break;
}
}
else
{
hsc_msg_eof(hp, "`>' expected");
*state = TGST_ERR;
}
return ((BOOL) ((*state == TGST_END) || (*state == TGST_ERR)));
}
/*
* skip_until_eot_args
*
* skip until end of tag reached,
* with user definable status vars
*
* params: inpf.....input file
* quote....status for quote (TRUE=inside quote)
* dquote...status for double quote
* argattr..status for quote
* result: TRUE, if no fatal error
* errors: return FALSE
*/
BOOL skip_until_eot_state(HSCPRC * hp, BYTE * state, EXPSTR * logstr)
{
INFILE *inpf = hp->inpf;
while (!eot_reached(hp, state))
if (logstr)
{
app_estr(logstr, infgetcws(inpf));
app_estr(logstr, infgetcw(inpf));
}
/* append ">" */
if (logstr)
{
app_estr(logstr, infgetcws(inpf));
app_estr(logstr, infgetcw(inpf));
}
return ((BOOL) ! (hp->fatal));
}
/*
* skip_until_eot
*
* skip until end of tag reached
*
* params: inpf..input file
* result: TRUE, if no fatal error
* errors: return FALSE
*/
BOOL skip_until_eot(HSCPRC * hp, EXPSTR * logstr)
{
BYTE state = TGST_TAG;
return (skip_until_eot_state(hp, &state, logstr));
}
/*
*-----------------
* skip comment
*-----------------
*/
/*
* eoc_reched
*
* check if end of an hsc-comment is reached
*
* params:
* inpf...where to read next word from
* state..state var; has to be initiales by
* calling func with CMST_TEXT
* nest...comment netsing counter; has to be
* initiales by calling func with 0
* result: TRUE, if end of comment reached
*/
BOOL eoc_reached(HSCPRC * hp, BYTE * state, LONG * nest)
{
INFILE *inpf = hp->inpf;
STRPTR nw = infgetw(inpf);
if (nw)
{
switch (*state)
{
case CMST_TEXT:
if (!strcmp(nw, "*"))
*state = CMST_STAR;
else if (!strcmp(nw, "<"))
*state = CMST_TAG;
break;
case CMST_STAR:
if (!strcmp(nw, "*"))
*state = CMST_STAR;
else if (!strcmp(nw, "<"))
*state = CMST_TAG;
else if (!strcmp(nw, ">"))
if (*nest)
{
(*nest)--;
*state = CMST_TEXT;
}
else
*state = CMST_END;
break;
case CMST_TAG:
if (!strcmp(nw, "<"))
*state = CMST_TAG;
else
{
if (!strcmp(nw, "*"))
(*nest)++;
*state = CMST_TEXT;
}
break;
}
}
else
{
hsc_msg_eof(hp, "missing end of comment (\"*>\")");
*state = CMST_ERR;
}
return ((BOOL) ((*state == CMST_END) || (*state == CMST_ERR)));
}
/*
* skip_hsc_comment
*
* skip text until '*>' occures;
* nested commets are supported
*
*/
BOOL skip_hsc_comment(HSCPRC * hp)
{
BYTE cstate = CMST_TEXT; /* vars for eoc_reached() */
LONG cnest = 0;
BOOL end = FALSE; /* end of comment reached? */
while (!end && !(hp->fatal))
{
end = eoc_reached(hp, &cstate, &cnest);
}
return ((BOOL) ! (hp->fatal));
}
/*
* skip_until_tag
*
* skip everythin, until a specific tag (one of tagstoplist or tagnest)
* is found.
*
* params:
* hp hsc-process to work with
* tagfound destination string that will store name of tag that lead
* to abortion of skip (eg "$else"); if this string is NULL,
* it will be ignored
* tagstoplist list of tags to stop on, sparated with vertical bars `|'
* eg. "$else|$elseif"
* tagnest single tag, that maintains a nesting-counter, depending
* on wheter it occures as a start-tag or not; if the
* nesting-counter is 0 and it occures as a stop-tag, it
* will also stop skipping (eg "$if")
*/
#define STATE_TEXT 1 /* normal text */
#define STATE_TAG 2 /* after "<" */
#define STATE_COMMENT 3 /* inside hsc-comment */
#define STATE_COMMENT_STAR 4 /* inside hsc-comment, after "*" */
#define STATE_TAG_STOP 5 /* found tag in stoplist */
#define STATE_SKIP 6 /* inside `skip section' "<|..|>" */
#define STATE_VBAR 7 /* inside `skip section', after "|" */
#define STATE_TAGNAME 8 /* after tagname */
#define STATE_ENDTAGNAME 9 /* after end-tagname */
#define STATE_TAGATTR 10 /* parsing tag-attribs */
#define STATE_TAGATTR_EQ 11 /* "=" inside tag */
#define STATE_TAGATTR_DQUOTE 12 /* double quote after "=" inside tag */
#define STATE_TAGATTR_SQUOTE 13 /* single quote after "=" inside tag */
#define STATE_COMMENT_TAG 14 /* found "<" inside comment (nest comment) */
#define STATE_EXIT_ERROR_EOF 99 /* unexpected eof */
BOOL skip_until_tag(HSCPRC * hp, EXPSTR * tagfound, STRPTR tagstoplist, STRPTR tagnest)
{
UBYTE state = STATE_TEXT; /* */
INFILE *inpf = hp->inpf; /* input file */
LONG nesting = 0; /* tag-nesting */
LONG nesting_comment = 0; /* comment-nesting */
STRPTR nw = NULL;
BOOL quit = FALSE; /* flag: exit from skipping */
EXPSTR *ungetstr = init_estr(32);
clr_estr(tagfound);
do
{
/* get next word or tag-id */
if (state != STATE_TAG)
nw = infgetw(inpf);
else
{
nw = infget_tagid(hp);
if (nw)
{
app_estr(ungetstr, infgetcws(inpf));
app_estr(ungetstr, infgetcw(inpf));
if (strcmp(nw, "/"))
{
DS(fprintf(stderr, DHLS "start-tag <%s>\n", nw));
state = STATE_TAGNAME; /* tag detected */
}
else
{
nw = infget_tagid(hp);
DS(fprintf(stderr, DHLS "end-tag </%s>\n", nw));
app_estr(ungetstr, infgetcws(inpf));
app_estr(ungetstr, infgetcw(inpf));
state = STATE_ENDTAGNAME; /* end-tag detected */
}
}
}
if (nw)
{
switch (state)
{
/* check if tag starts */
case STATE_TEXT:
if (!strcmp(nw, "<"))
{
DS(fprintf(stderr, DHLS "tag\n"));
set_estr(ungetstr, nw);
state = STATE_TAG;
}
break;
/* check which tag it is and how to act */
case STATE_TAGNAME:
{
/* check, if nesting-tag should be incr. */
if (!upstrcmp(nw, tagnest))
{
DS(fprintf(stderr, DHLS "nest-tag (%ld)\n", nesting));
state = STATE_TAGATTR;
nesting++;
}
/* check, if stop-tag reached */
else if (!nesting
&& strenum(nw, tagstoplist, '|', STEN_NOCASE))
{
DS(fprintf(stderr, DHLS "stop-tag `%s'\n", nw));
set_estr(tagfound, nw);
quit = TRUE;
}
/* check, if commant-tag reached */
else if (!strcmp(nw, HSC_COMMENT_STR))
{
DS(fprintf(stderr, DHLS "comment-tag (0)\n"));
state = STATE_COMMENT;
}
/* any tag; just skip attributes */
else
{
DS(fprintf(stderr, DHLS "any tag\n"));
state = STATE_TAGATTR;
}
break;
}
case STATE_ENDTAGNAME:
{
if (!upstrcmp(nw, tagnest))
{
if (nesting)
{
nesting--;
DS(fprintf(stderr, DHLS "nest-tag (%ld)\n", nesting));
}
else
{
DS(fprintf(stderr, DHLS "nest-tag ending\n"));
quit = TRUE;
}
}
else
state = STATE_TEXT; /* no attr for endtag */
break;
}
/*
* process tag attributes
*/
case STATE_TAGATTR:
{
if (!strcmp(nw, "="))
state = STATE_TAGATTR_EQ;
else if (!strcmp(nw, ">"))
{
DS(fprintf(stderr, DHLS "back to text\n"));
state = STATE_TEXT;
}
break;
}
case STATE_TAGATTR_EQ:
{
if (!strcmp(nw, "\""))
{
DS(fprintf(stderr, DHLS "tagarg (double quote)\n"));
state = STATE_TAGATTR_DQUOTE;
}
else if (!strcmp(nw, "'"))
{
DS(fprintf(stderr, DHLS "tagarg (single quote)\n"));
state = STATE_TAGATTR_SQUOTE;
}
else
state = STATE_TAGATTR;
break;
}
case STATE_TAGATTR_DQUOTE:
{
if (!strcmp(nw, "\""))
{
DS(fprintf(stderr, DHLS "end tagarg (double quote)\n"));
state = STATE_TAGATTR;
}
break;
}
case STATE_TAGATTR_SQUOTE:
{
if (!strcmp(nw, "'"))
{
DS(fprintf(stderr, DHLS "end tagarg (single quote)\n"));
state = STATE_TAGATTR;
}
break;
}
/*
* comment processing
*/
case STATE_COMMENT:
{
/* check for <" */
if (!strcmp(nw, "<"))
state = STATE_COMMENT_TAG;
else if (!strcmp(nw, HSC_COMMENT_STR))
state = STATE_COMMENT_STAR;
break;
}
case STATE_COMMENT_TAG:
{
/* check for comment-nesting */
if (!strcmp(nw, HSC_COMMENT_STR))
{
nesting_comment++;
DS(fprintf(stderr, DHLS "comment-tag (%ld)\n", nesting_comment));
state = STATE_COMMENT;
}
else
state = STATE_COMMENT;
break;
}
case STATE_COMMENT_STAR:
{
/* check for end comment */
if (!strcmp(nw, ">"))
if (nesting_comment)
{
nesting_comment--;
DS(fprintf(stderr, DHLS "end comment-tag (%ld)\n", nesting_comment));
state = STATE_COMMENT;
}
else
{
DS(fprintf(stderr, DHLS "end comment-tag (%ld)\n", nesting_comment));
state = STATE_TEXT;
}
else
state = STATE_COMMENT;
break;
}
/*
* unhandled tag
*/
default:
panic("unhandled state");
break;
}
}
}
while (nw && !quit && !(hp->fatal));
if (nw)
{
inungets(estr2str(ungetstr), inpf);
}
else
{
EXPSTR *tagstr = init_estr(0);
set_estr(tagstr, "</");
app_estr(tagstr, tagnest);
app_estr(tagstr, "> expected");
hsc_msg_eof(hp, estr2str(tagstr));
del_estr(tagstr);
}
del_estr(ungetstr);
return ((BOOL) (nw != NULL));
}